package edu.kit.los.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.google.gson.Gson;

import edu.kit.los.event.StandartEvent;
import edu.kit.los.event.FacebookEvent;

/**
 * @author felix,bene 
 * 
 * Hilfsklasse, die unter anderem verschiedene
 * Methoden zur Konvertierung in JSON, KML und HTML bereitstellt
 */
public class Converter {
	
	static SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd-hh:mm:ss");

	/**
	 * Konvertiert eine Datum im Facebook-Format (zum Beispiel
	 * 2011-11-17T00:10:56 oder 2011-11-27T00:10:56+0000 in ein Date-Objekt.
	 * 
	 * @param s
	 *            String der umgewandelt werden soll
	 * @return Instanz von java.util.Date mit dem zugeh�rigen Datum. Falls das
	 *         Datum nicht gecastet werden kann, so wird die Instanz Date(0)
	 *         (=01.01.1970 00:00:00) zur�ckgegeben.
	 */
	public static Date FacebookDate2JavaDate(String s) {
		s = s.replace("T", "-");
		// Calendar cal = Calendar.getInstance();
		Date d;
		try {
			d = df.parse(s);
		} catch (ParseException e) {
			d = new Date(0);
		}
		return d;
		// cal.setTime(d1);
		// return cal;
	}

	/**
	 * String f�r Beginn der HTML-Seite
	 */
	public static final String HTMLHead = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//DE\""
			+ "\"http://www.w3.org/TR/html4/strict.dtd\">\n"
			+ "<html>\n"
			+ "<body>\n" + "<table border=\"1\" cellspacing=\"0\">\n";
	/**
	 * String f�r Ende der HTML-Seite
	 */
	public static final String HTMLTail = "</table>\n" + "</body>\n"
			+ "</html\n";
	/**
	 * Erste Zeile der Tabelle
	 */
	public static final String HTMLHeadline = "<tr>\n" + "  <th>" + "ID"
			+ "</th>\n" + "  <th>" + "name" + "</th>\n" + "  <th>"
			+ "description" + "</th>\n" + "  <th>" + "start_time" + "</th>\n"
			+ "  <th>" + "end_time" + "</th>\n" + "  <th>" + "updated_time"
			+ "</th>\n" + "  <th>" + "privacy" + "</th>\n" + "  <th>"
			+ "owner_name" + "</th>\n" + "  <th>" + "owner_ID" + "</th>\n"
			+ "  <th>" + "location" + "</th>\n" + "  <th>" + "geo_lat"
			+ "</th>\n" + "  <th>" + "geo_long" + "</th>\n" + "  <th>"
			+ "geo_ID" + "</th>\n" + "</tr>\n";;

	/**
	 * String f�r Beginn der KML-Datei
	 */

	public static final String KMLHead = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <kml xmlns=\"http://www.opengis.net/kml/2.2\"> <Document>";
	/**
	 * String f�r Ende der KML-Datei
	 */
	public static String KMLTail = "</Document>" + "</kml>";

	/**
	 * Erzeugt aus einer Liste von FacebookEvents ein HTML-Tabelle
	 * 
	 * @param list
	 *            Liste der FacebookEvents
	 * @return HTML-Tabelle (String)
	 */
	public static String FacebookEventList2HTML(List<FacebookEvent> list) {
		String result = "";
		result += HTMLHead;
		result += HTMLHeadline;
		for (FacebookEvent fbe : list)
			result += facebookEvent2HTML(fbe);
		result += HTMLTail;
		return result;
	}

	/**
	 * Erzeugt aus einer Liste von FacebookEvents eine KML-Datei
	 * 
	 * @param list
	 *            Liste der FacebookEvents
	 * @return KML-Datei (String)
	 */
	public static String FacebookEventList2KML(List<FacebookEvent> list) {
		StringBuilder sb = new StringBuilder();
		sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <kml xmlns=\"http://www.opengis.net/kml/2.2\"> <Document>");
		// sb.append(KMLHead);
		for (FacebookEvent fbe : list)
			sb.append(facebookEvent2KML(fbe));
		sb.append(KMLTail);
		return sb.toString();
	}

	/**
	 * Generiert das JSON Objekt, das von der Google Maps API zum Anzeigen der
	 * Events benötigt wird
	 * 
	 * @param Liste von Events
	 * @return JSON Objekt zur Anzeige auf Google Maps API
	 */
	public static String GoogleMapsJson(List<StandartEvent> list) {

		Gson gson = new Gson();
		List<GoogleMapJson> eventlist = new LinkedList<GoogleMapJson>();
		for (StandartEvent event : list) {
			// nehme nur Events mit GeoAngaben
			if (event.getGeoLat() != 0 && event.getGeoLong() != 0) {
				GoogleMapJson prototype = new GoogleMapJson();
				prototype.setContent(Converter.contentHtml(event));
				double[] location = { event.getGeoLat(), event.getGeoLong() };
				prototype.setLocation(location);
				prototype.setName(event.getName());
				eventlist.add(prototype);
			}
		}
		StringBuilder sb = new StringBuilder();
		sb.append("{ 'events' : ");
		sb.append(gson.toJson(eventlist.toArray()));
		sb.append("}");
		System.out.println(sb.toString());
		return sb.toString();
	}

	/**
	 * Erzeugt das Html, das im InfoWindow angezeigt wird, wenn der Benutzer auf
	 * der Karte auf ein EventPrototype klickt TODO: verschönern
	 * 
	 * @param Ein EventPrototype
	 * @return Der im InfoWindow anzuzeigend HTML Text (als String)
	 */
	public static String contentHtml(StandartEvent event) {
		StringBuilder sb = new StringBuilder();
		sb.append(HTMLHead);
		sb.append("<span style=\"font-size:1.2em\" \"font-weight:bold\">"
				+ event.getName() + "</span><br>");
		sb.append("<a href=\""+event.getURL()+"\">Event anschauen</a> <br>");
		if (event.getStart_time()==null
				|| event.getStart_time().equals("")) {
			System.out.println("Im Nullblock");
		}
		else{
			sb.append("<br>Start: " + event.getStart_time() + "<br>");
		}
		if (!(event.getEnd_time()==null)
				&& !event.getEnd_time().equals("")) {
			sb.append("End: " + event.getEnd_time() + "<br>");
		}
		if (!(event.getLocation()==null)
				&& !(event.getLocation().equals(""))) {
			sb.append("Location: " + event.getLocation() + "<br>");
		}
		if (!(event.getDescription()==null)
				&& !(event.getDescription().equals(""))) {
			sb.append("<br>" + event.getDescription() + "<br>");
		}

		return sb.toString();
	}

	/**
	 * Stellt ein FacebookEvent als Zeile einer Tabelle dar.
	 * 
	 * @return Tabellenzeile (HTML-Code)
	 */
	public static String facebookEvent2HTML(FacebookEvent fe) {
		String result = "" + "<tr>\n" + "  <td>" + fe.getId() + "</td>\n"
				+ "  <td>" + fe.getName() + "</td>\n" + "  <td>"
				+ fe.getDescription() + "</td>\n" + "  <td>"
				+ fe.getStart_time() + "</td>\n" + "  <td>" + fe.getEnd_time()
				+ "</td>\n" + "  <td>" + fe.getUpdated_time() + "</td>\n"
				+ "  <td>" + fe.getPrivacy() + "</td>\n" + "  <td>"
				+ fe.getOwnerName() + "</td>\n" + "  <td>" + fe.getOwnerID()
				+ "</td>\n" + "  <td>" + fe.getLocation() + "</td>\n"
				+ "  <td>" + fe.getGeoLat() + "</td>\n" + "  <td>"
				+ fe.getGeoLong() + "</td>\n" + "  <td>" + fe.getGeoID()
				+ "</td>\n" + "</tr>\n";
		return result;
	}

	/**
	 * Erzeugt einen Punkt (Placemark) f�r eine KML-Datei mit folgenden Infos:
	 * Name, Description, Koordinaten.
	 * 
	 * @return Darstellung des Punktes im KML-Format
	 */
	public static String facebookEvent2KML(FacebookEvent fe) {
		String description = fe.getDescription();
		if (description != null) {
			description = description.replace("&", "and");
			description = kuerzen(description, 300);
		}
		String name = fe.getName();
		if (name != null) {
			name = name.replace("&", "and");
			name = kuerzen(name, 80);
		}
		String datum = fe.getStart_time().toString();
		if (name == null)
			datum = "unbekannt";
		datum = "Startdatum: " + datum;

		String beschreibungHTML = datum + "<br />" + description + "<br />"
				+ "<a href=\"http://www.facebook.com/" + fe.getId()
				+ "\">EventPrototype auf Facebook anschauen</a>";

		String result = "" + "  <Placemark>" + "    <name>" + name + "</name>"
				+ "    <description>" + beschreibungHTML + "</description>"
				+ "    <Point>" + "      <coordinates>" + fe.getGeoLat() + ","
				+ fe.getGeoLong() + ",0</coordinates>" + "    </Point>"
				+ "  </Placemark>";
		return result;
	}

	/**
	 * verk�rzt einen �bergebenen String auf eine anzugebende L�nge und f�gt 3
	 * Punkte am Ende hinzug //TODO: Kann man das wieder expandieren??
	 * 
	 * @param str
	 *            zu k�rzender String
	 * @param length
	 *            gew�nschte L�nge (exklusive ...). Wird keine L�nge angegeben,
	 *            so wird der String auf eine standardm��ige L�nge gek�rzt.
	 * @return gek�rzten String (falls l�nger als Wunschl�nge)
	 */
	public static String kuerzen(String str, int length) {
		// Wenn String null, abbrechen
		if (str == null)
			return null;
		// Standardwert f�r die L�nge
		if (length == 0)
			length = 150;
		// falls schon kurz genug, Ursprungsstring zur�ckgeben
		if (str.length() < length)
			return str;
		// gek�rzter String mit ...
		// else return "XXX";
		else
			return str.substring(0, length - 1) + " ...";
	}
}
